package com.heima.article.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.heima.apis.IWemediaClient;
import com.heima.article.mapper.ApArticleMapper;
import com.heima.article.service.HotArticleService;
import com.heima.common.constants.ArticleConstants;
import com.heima.model.article.pojos.ApArticle;
import com.heima.model.article.vos.HotArticleVo;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.wemedia.pojos.WmChannel;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Calendar;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class HotArticleServiceImpl implements HotArticleService {
    @Autowired
    private ApArticleMapper articleMapper;

    @Autowired
    private IWemediaClient wemediaClient;

    @Autowired
    private StringRedisTemplate redisTemplate;


    /**
     * 计算热点文章
     */
    @Override
    public void computeHotArticle() {
        // 1.查询前五天的文章列表
        List<ApArticle> articleList = getArticleBefore5Day();
        // 2.计算分值
        List<HotArticleVo> hotArticleVoList = getHotArticleVos(articleList);
        // 3.缓存到redis
        if (hotArticleVoList == null || hotArticleVoList.size() == 0) {
            return;
        }
        ResponseResult<List<WmChannel>> responseResult = wemediaClient.findAll();
        if (responseResult.getCode() != 200) {
            return;
        }
        List<WmChannel> channelList = responseResult.getData();
        if (channelList == null || channelList.size() == 0) {
            return;
        }
        // 保存频道热点文章到redis
        for (WmChannel wmChannel : channelList) {
            List<HotArticleVo> channelArticleList = hotArticleVoList.stream().filter(
                    hotArticleVo -> hotArticleVo.getChannelId().equals(wmChannel.getId())
            ).collect(Collectors.toList());
            cacheToRedis(channelArticleList, ArticleConstants.HOT_ARTICLE_FIRST_PAGE + wmChannel.getId());
        }
        // 保存推荐热点文章到redis
        cacheToRedis(hotArticleVoList, ArticleConstants.HOT_ARTICLE_FIRST_PAGE + "__all__");
    }

    /**
     * 保存30篇热点文章到缓存
     * @param channelArticleList
     * @return
     */
    private void cacheToRedis(List<HotArticleVo> channelArticleList, String key) {
        channelArticleList = channelArticleList.stream()
                .sorted(Comparator.comparing(HotArticleVo::getPublishTime).reversed())
                .limit(30)
                .collect(Collectors.toList());
        redisTemplate.opsForValue().set(key, JSON.toJSONString(channelArticleList));
    }

    /**
     * 计算热点文章分值
     *
     * @param articleList
     * @return
     */
    private List<HotArticleVo> getHotArticleVos(List<ApArticle> articleList) {
        if (articleList == null || articleList.size() == 0) {
            return null;
        }
        return articleList.stream().map(
                apArticle -> {
                    HotArticleVo vo = new HotArticleVo();
                    BeanUtils.copyProperties(apArticle, vo);
                    vo.setScore(calArticleScore(apArticle));
                    return vo;
                }
        ).collect(Collectors.toList());
    }

    /**
     * 计算每篇文章的分值
     *
     * @param apArticle
     * @return
     */
    private Integer calArticleScore(ApArticle apArticle) {
        Integer score = 0;
        if (apArticle.getLikes() != null) {
            score += apArticle.getLikes() * ArticleConstants.HOT_ARTICLE_LIKE_WEIGHT;
        }
        if (apArticle.getViews() != null) {
            score += apArticle.getViews() * ArticleConstants.HOT_ARTICLE_READ_WEIGHT;
        }
        if (apArticle.getComment() != null) {
            score += apArticle.getComment() * ArticleConstants.HOT_ARTICLE_COMMENT_WEIGHT;
        }
        if (apArticle.getCollection() != null) {
            score += apArticle.getCollection() * ArticleConstants.HOT_ARTICLE_COLLECTION_WEIGHT;
        }
        return score;
    }

    private List<ApArticle> getArticleBefore5Day() {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DAY_OF_MONTH, -5);
        return articleMapper.findArticleListByLast5days(calendar.getTime());
    }
}
